//////////////////
// minimips.cpp //
//////////////////
#include "systemc.h"

#include "channel.h"
#include "random.h"
#include "structs.h"

#include "fetch.cpp"
#include "imem.cpp"
#include "decode.cpp"
#include "execute.cpp"
#include "dmem.cpp"

int sc_main (int argc, char* argv[])
{
//-------------Declarações----------------------------------------------------//
	async_channel< sc_uint<32> > feim_pc;
	async_channel< sc_uint<32> > imfe_instruction;
	async_channel< sc_uint<32> > fede_instruction;
	async_channel< deex > deex_struct;
	async_channel< exdm > exdm_struct;
	async_channel< sc_int<32> > dmde_data_out;
	async_channel< sc_int<32> > dedm_data_in;
	async_channel< sc_int<32> > exde_rd;
	async_channel< sc_uint<1> > exfe_branch_decision;
//----------------------------------------------------------------------------//


//-------------Atribuições----------------------------------------------------//

	fetch fetch1("FETCH");
	fetch1.imem_address(feim_pc);
	fetch1.imem_data(imfe_instruction);
	fetch1.fede_instruction(fede_instruction);
	fetch1.exfe_branch_decision(exfe_branch_decision);

	imem imem1("IMEM");
	imem1.imem_address(feim_pc);
	imem1.imem_data(imfe_instruction);

	decode decode1("DECODE");
	decode1.fede_instruction(fede_instruction);
	decode1.deex_struct(deex_struct);
	decode1.dmde_data_out(dmde_data_out);
	decode1.dedm_data_in(dedm_data_in);
	decode1.exde_rd(exde_rd);

	execute execute1("EXECUTE");
	execute1.deex_struct(deex_struct);
	execute1.exdm_struct(exdm_struct);
	execute1.exde_rd(exde_rd);
	execute1.exfe_branch_decision(exfe_branch_decision);

	dmem dmem1("DMEM");
	dmem1.exdm_struct(exdm_struct);
	dmem1.data_in(dedm_data_in);
	dmem1.data_out(dmde_data_out);

//----------------------------------------------------------------------------//


//-------------Execução-------------------------------------------------------//
	// Open VCD file
	sc_trace_file *wf = sc_create_vcd_trace_file("minimips-systemc");
	wf->set_time_unit(1, SC_NS);
	// Dump the desired signals
	sc_trace(wf, feim_pc.data, "feim.pc");
	sc_trace(wf, imfe_instruction.data, "imfe.instr");
	sc_trace(wf, fede_instruction.data, "fede.instr");
	sc_trace(wf, deex_struct.data.op, "deex.op");
	sc_trace(wf, deex_struct.data.func, "deex.func");
	sc_trace(wf, deex_struct.data.offset, "deex.offset");
	sc_trace(wf, deex_struct.data.rs, "deex.rs_dt");
	sc_trace(wf, deex_struct.data.rt, "deex.rt_dt");
	sc_trace(wf, deex_struct.data.rd, "deex.rd_dt");
	sc_trace(wf, exdm_struct.data.rd, "exdm.rd");
	sc_trace(wf, exdm_struct.data.rw, "exdm.rw");
	sc_trace(wf, dmde_data_out.data, "dmde.dout");
	sc_trace(wf, dedm_data_in.data, "dedm.din");
	sc_trace(wf, exde_rd.data, "exde.rd");
	sc_trace(wf, exfe_branch_decision.data, "exfe.bd");

	cout << "Seed: " << SetRandomSeed() << endl;
	
	sc_start(1000,SC_NS);

	sc_close_vcd_trace_file(wf);
	return 0;
//----------------------------------------------------------------------------//
}